home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / amiga / hdf / hdf.lha / DFIMCOMP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1980-02-06  |  35.8 KB  |  1,260 lines

  1. /*****************************************************************************
  2. *              NCSA HDF version 3.10r3
  3. *                Dec 6, 1990
  4. *
  5. * NCSA HDF Version 3.10r3 source code and documentation are in the public
  6. * domain.  Specifically, we give to the public domain all rights for future
  7. * licensing of the source code, all resale rights, and all publishing rights.
  8. * We ask, but do not require, that the following message be included in all
  9. * derived works:
  10. * Portions developed at the National Center for Supercomputing Applications at
  11. * the University of Illinois at Urbana-Champaign.
  12. * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE
  13. * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION,
  14. * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE
  15. *****************************************************************************/
  16.  
  17. #ifdef RCSID
  18. static char RcsId[] = "@(#)$Revision: 3.4 $";
  19. #endif
  20. /*
  21. $Header: /pita/work/HDF/dev/RCS/src/dfimcomp.c,v 3.4 90/07/02 10:12:07 clow beta $
  22.  
  23. $Log:    dfimcomp.c,v $
  24.  * Revision 3.4  90/07/02  10:12:07  clow
  25.  * some cosmetic modifications
  26.  * 
  27. */
  28. /************************************************************************/
  29. /*  Module Name : imcomp                        */
  30. /*  Exports     : DFCimcomp(), DFCunimcomp()                */
  31. /*  Purpose     : Compresses color images               */
  32. /*  Author  : Eng-Kiat Koh                      */
  33. /*  Date    : June 30th, 1988                   */
  34. /*  Functions   : DFCimcomp(), compress(), init_global(), cnt_color()   */
  35. /*        set_palette(), fillin_color(), map(), nearest_color() */
  36. /*        DFCunimcomp(), sqr()                                  */
  37. /************************************************************************/
  38.  
  39. struct rgb
  40. {
  41.     unsigned char c[3];
  42. };
  43.  
  44. #include "df.h"
  45.  
  46. #define PALSIZE 256
  47. #define BIT8 0
  48. #define BIT24 1
  49.  
  50. #ifndef MAC
  51. #define MAXCOLOR 32768
  52. #else /*MAC*/
  53. #define MAXCOLOR 768
  54. #endif /*MAC*/
  55.  
  56. #ifndef NULL
  57. #   define NULL 0
  58. #endif
  59.  
  60. #define RED 0
  61. #define GREEN 1
  62. #define BLUE 2
  63. #define EPSILON 0.5
  64. #define LO 1
  65. #define HI 0
  66.  
  67. /* struct rgb
  68. {
  69.   unsigned char c[3];
  70. };
  71. */
  72. struct box
  73. {
  74.   float bnd[3][2];
  75.   int *pts;
  76.   int nmbr_pts;
  77.   int nmbr_distinct;
  78.   struct box *left;
  79.   struct box *right;
  80. };
  81.  
  82.  
  83. unsigned char *new_pal;          /* pointer to new palette           */
  84.  
  85.  
  86. static int *hist = (int *)NULL;    /* histogram for distinct colors    */
  87. static struct box *frontier = (struct box *)NULL; /* pointer to the */
  88.                           /* list of boxes */
  89. static struct rgb *distinct_pt = (struct rgb *)NULL; /* contains all */
  90.                              /* distinct rgb points */
  91.  
  92. static void sel_palette(int, int, struct rgb *); 
  93. static void compress();
  94. static void init_global();
  95. static int cnt_color();
  96. static void set_palette();
  97. static void fillin_color();
  98. static int indx();
  99. static void map();
  100. static int nearest_color();
  101. static long int sqr();
  102. static void init(int, int, struct rgb *);
  103. static int partition();
  104. static struct box *find_box();
  105. static void split_box();
  106. static void assign_color();
  107. static int select_dim();
  108. static float find_med();
  109. static void classify();
  110. static int next_pt();
  111.  
  112. /* extern char *calloc(); */
  113.  
  114. static struct rgb *color_pt = (struct rgb *)NULL; /*contains the hi-lo */
  115.                           /*colors for each block*/
  116. static unsigned char *image;    /* contains the compressed image            */
  117. static int trans[MAXCOLOR];     /* color translation table                  */
  118.  
  119. /************************************************************************/
  120. /*  Function    : DFCimcomp                                             */
  121. /*  Purpose : Performs Imcomp Compression                           */
  122. /*  Parameters  :                                                       */
  123. /*    xdim, ydim - dimensions of image                                  */
  124. /*                 IT IS ASSUMED THAT THE DIMENSIONS ARE A MULTIPLE OF 4*/
  125. /*    in, out    - input image array and output image buffer size of in */
  126. /*                 is xdim*ydim bytes for 8 bit per pixel mode. It is 3 */
  127. /*                 times that for 24 bits per pixel mode. The output    */
  128. /*                 buffer is always (xdim*ydim)/4.                      */
  129. /*    in_pal     - input palette. Consist of rgb triples unlike seq-type*/
  130. /*                 palette. This is a NULL pointer if operating at the  */
  131. /*                 24 bit per pixel mode.                               */
  132. /*    out_pal    - output palette. Consist of PALSIZE color entries.    */
  133. /*                 each entry is an rgb triple.                         */
  134. /*    mode       - Either BIT8 or BIT24                                 */
  135. /*  Returns     : none                          */
  136. /*  Called by   : External routines                                     */
  137. /*  Calls       : init_global(), compress(), cnt_color(), set_palette(),*/
  138. /*        sel_palette(), map()                                  */
  139. /************************************************************************/
  140.  
  141. void DFCimcomp(xdim, ydim, in, out, in_pal, out_pal, mode)
  142. int32 xdim, ydim;
  143. int mode;
  144. char in[], out[], in_pal[], out_pal[];
  145. {
  146.   unsigned char raster[48];
  147.   int blocks, nmbr, i, j, k, l, x, y;
  148.   void init_global();
  149.   void compress();
  150.   int cnt_color();
  151.   void set_palette();
  152.   void sel_palette(int, int, struct rgb *);
  153.   void map();
  154.   void fillin_color();
  155.  
  156.   init_global(xdim, ydim, out, out_pal);
  157.  
  158.   /* compress pixel blocks */
  159.   blocks = 0;
  160.   for (i=0; i<(ydim/4); i++)
  161.     for (j=0; j<(xdim/4); j++)
  162.     {
  163.       switch (mode)
  164.       {
  165.         case BIT8 : /* 8 bit per pixel format */
  166.             k = 0;
  167.             for (y=(i*4); y<(i*4+4); y++)
  168.               for (x=(j*4); x<(j*4+4); x++)         
  169.               {
  170.             l = y*xdim + x;
  171.             raster[k++] = (unsigned char) in_pal[3 * (unsigned char)in[l]];
  172.             raster[k++] = (unsigned char) in_pal[3 * (unsigned char)in[l] + 1];
  173.             raster[k++] = (unsigned char) in_pal[3 * (unsigned char)in[l] + 2];
  174.               } /* end of for x */
  175.             compress(raster,blocks);
  176.             break;
  177.  
  178.       case BIT24: /* 24 bit per pixel format */
  179.             k = 0;
  180.             for (y=(i*4); y<(i*4+4); y++)
  181.               for (x=(j*4); x<(j*4+4); x++)         
  182.               {
  183.             l = 3 *(y*xdim + x);
  184.             raster[k++] = (unsigned char) in[l];
  185.             raster[k++] = (unsigned char) in[l+1];
  186.             raster[k++] = (unsigned char) in[l+2];
  187.               } /* end of for x */
  188.             compress(raster,blocks);
  189.             break;
  190.     
  191.     default   : /* unsupported format */
  192.             printf("Error : Unsupported Format \n");
  193.             exit(1);
  194.             break;
  195.       } /* end of switch */
  196.       
  197.       blocks++;
  198.     } /* end of for j */
  199.  
  200.   /* set palette */
  201.   nmbr = cnt_color(blocks);
  202. /*
  203.   printf("Number of colors %d \n", nmbr);
  204. */
  205.   if (nmbr <= PALSIZE)
  206.     set_palette(blocks);
  207.   else
  208.   {
  209.     sel_palette(blocks,nmbr,color_pt);
  210.     map(blocks);
  211.   }
  212.  
  213.   fillin_color(blocks);
  214.  
  215. } /* end of DFCimcomp */
  216.  
  217.  
  218.  
  219.  
  220.  
  221.  
  222. /************************************************************************/
  223. /*  Function    : compress                                  */
  224. /*  Purpose : Given a block of 16 pixels, sets up a 16 bit bitmap   */
  225. /*                and assigns a lo and hi color for the block. For block*/
  226. /*                i, hi color is stored in color_pt[2i] and lo in       */
  227. /*                color_pt[2i+1]. Each color is then reduced to 15 bits */
  228. /*                by truncating the lower order 3 bits of each component*/
  229. /*  Parameter   :                           */
  230. /*    raster     - contains the 16 pixels of a block. Each pixel is 3   */
  231. /*         bytes, 1 byte for each color component               */
  232. /*    block  - pixel block number                                   */
  233. /*  Returns     : none                                                  */
  234. /*  Called by   : DFCimcomp()                       */
  235. /*  Calls       : none                          */
  236. /************************************************************************/
  237.  
  238. static void compress(raster, block)
  239. unsigned char raster[];
  240. int block;
  241. {
  242.   float y[16], y_av;
  243.   int i, j, k, l, bit;
  244.   int high, hi, lo;
  245.   int c_hi[3], c_lo[3];
  246.  
  247.   /* calculate luminance */
  248.   y_av = 0.0;
  249.   for (i=0; i<16; i++)
  250.   {
  251.     j = 3*i;
  252.     y[i] = 0.3*(float)raster[j] + 0.59*(float)raster[j+1] + 
  253.            0.11*(float)raster[j+2];
  254. /*    printf("compress: y[%d] is %f\n",i,y[i]);*/
  255.     y_av = y_av + y[i];
  256.   }
  257.   y_av = y_av / 16.0;
  258. /*  printf("y_av is %f\n",y_av); */
  259.  
  260.   /* initialize c_hi and c_lo */
  261.   for (i=RED; i<=BLUE; i++)
  262.   {
  263.     c_hi[i] = 0;
  264.     c_lo[i] = 0;
  265.   }
  266.  
  267.   /* build bit map */
  268.   k = 4 * block;
  269.   high = 0;
  270.   hi = 2 * block;
  271.   lo = hi + 1;
  272.   for (i=0; i<2; i++)
  273.   {
  274.     bit = 128;
  275.     for (j = (i*8); j<(i*8+8); j++)
  276.     {
  277.       if (y[j] > y_av)
  278.       {
  279.     image[k] = image[k] | bit;
  280.     high++;
  281.         for (l=RED; l<= BLUE; l++)
  282.       c_hi[l] = c_hi[l] + (int)raster[3*j+l];
  283.       }
  284.       else
  285.       {
  286.     for (l=RED; l<=BLUE; l++)
  287.           c_lo[l] = c_lo[l] + (int)raster[3*j+l];
  288.       } /* end of if */
  289.  
  290.       bit = bit >> 1;
  291.     } /* end of for j */
  292.    
  293.     k++;
  294.   } /* end of for i */
  295.  
  296.   /* calculate hi lo color */
  297.   for (i=RED; i<=BLUE; i++)
  298.   {
  299.     if (high != 0)
  300.       color_pt[hi].c[i] = (int)((float)c_hi[i] / (float)high);
  301.     if (high != 16)
  302.       color_pt[lo].c[i] = (int)((float)c_lo[i] / (float)(16 - high));
  303.     color_pt[hi].c[i] = color_pt[hi].c[i] >> 3;
  304.     color_pt[lo].c[i] = color_pt[lo].c[i] >> 3;
  305.  
  306.   }
  307. } /* end of compress */
  308.  
  309.  
  310.  
  311.  
  312.  
  313.  
  314. /************************************************************************/
  315. /*  Function    : init_global                       */
  316. /*  Purpose : Allocates memory for global variables                 */
  317. /*  Parameter   :                           */
  318. /*    xdim, ydim - x and y dimension of image               */
  319. /*    out        - pointer to output buffer                             */
  320. /*    out_pal    - pointer to output palette                            */
  321. /*  Returns     : none                              */
  322. /*  Called by   : DFCimcomp()                       */
  323. /*  Calls       : none                          */
  324. /************************************************************************/
  325.  
  326. static void init_global(xdim, ydim, out, out_pal)
  327. int32 xdim, ydim;
  328. char *out, *out_pal;
  329. {
  330.   int i, j;
  331.  
  332.   /* allocate memory */
  333.   image = (unsigned char *) out;
  334.   new_pal = (unsigned char *) out_pal;
  335.   if (color_pt) DFIfreespace((char *) color_pt);
  336.   color_pt = (struct rgb *)DFIgetspace((unsigned)((xdim*ydim)/8) *
  337.                        sizeof(struct rgb));
  338.  
  339.   if (image == NULL || color_pt == NULL || new_pal == NULL)
  340.   {
  341.     printf("Error : Out of Memory\n");
  342.     exit(1);
  343.   }
  344.  
  345.   /* initialize */
  346.   for (i=0; i<(xdim*ydim/4); i++)
  347.     image[i] = 0;
  348.  
  349.   for (i=0; i<(xdim*ydim/8); i++)
  350.     for (j=RED; j<= BLUE; j++)
  351.       color_pt[i].c[j] = 0;
  352.  
  353.   for (i=0; i<MAXCOLOR; i++)
  354.     trans[i] = -1;
  355. } /* end of init_global */
  356.  
  357.  
  358.  
  359.  
  360.  
  361. /************************************************************************/
  362. /*  Function    : cnt_color                                 */
  363. /*  Purpose : Counts the number of distinct colors compressd image  */
  364. /*  Parameter   :                           */
  365. /*    blocks     - total number of pixel blocks             */
  366. /*  Returns     : Number of distinct colors                             */
  367. /*  Called by   : DFCimcomp()                                           */
  368. /*  Calls       : indx()                        */
  369. /************************************************************************/
  370.  
  371. static int cnt_color(blocks)
  372. int blocks;
  373. {
  374.   int temp[MAXCOLOR];
  375.   int i, k, count;
  376.   int indx();
  377.  
  378.   for (i=0; i<MAXCOLOR; i++)
  379.     temp[i] = -1;
  380.  
  381.   for (i=0; i<(2*blocks); i++)
  382.   {
  383.     k = indx(color_pt[i].c[RED],color_pt[i].c[GREEN],color_pt[i].c[BLUE]);
  384. /*    printf("cnt_color: k is %d\n",k); */
  385.     temp[k] = 0;
  386.   }
  387.  
  388.   count  = 0;
  389.   for (i = 0; i< MAXCOLOR; i++)
  390.     if (temp[i] == 0)
  391.       count++;
  392.  
  393.   return count;
  394. } /* end of cnt_color */
  395.  
  396.  
  397.  
  398.  
  399.  
  400. /************************************************************************/
  401. /*  Function    : set_palette                       */
  402. /*  Purpose : The number of distinct colors is less than the desired*/
  403. /*                output palette size. Therefore each distinct color can*/
  404. /*        be a palette entry. Function enters each distinct     */
  405. /*                color as a palette entry and sets up the translation  */
  406. /*                table. It also shifts each color component left 3 bits*/
  407. /*                so that each color component is again 8 bits wide     */
  408. /*  Parameter   :                           */
  409. /*    blocks     - total number of pixel blocks                         */
  410. /*  Returns     : none                          */
  411. /*  Called by   : DFCimcomp()                       */
  412. /*  Calls       : indx()                        */
  413. /************************************************************************/
  414.  
  415. static void set_palette(blocks)
  416. int blocks;
  417. {
  418.   int ent, i, k;
  419.   int indx();
  420.  
  421.   ent = 0;
  422.   for (i = 0; i<(2*blocks); i++)
  423.   {
  424.     k = indx(color_pt[i].c[RED],color_pt[i].c[GREEN],color_pt[i].c[BLUE]);
  425.     if (trans[k] == -1)
  426.     {
  427.       new_pal[3*ent] = color_pt[i].c[RED] << 3;
  428.       new_pal[3*ent+1] = color_pt[i].c[GREEN] << 3;
  429.       new_pal[3*ent+2] = color_pt[i].c[BLUE] << 3;  
  430.       trans[k] = ent;
  431.       ent++;
  432.     }
  433.   }
  434. } /* end of set_palette */
  435.  
  436.  
  437.  
  438.  
  439.  
  440. /************************************************************************/
  441. /*  Function    : fillin_color                      */
  442. /*  Purpose : For each pixel block, fills in the pointers into the  */
  443. /*                palette.                                              */
  444. /*  Parameter   :                           */
  445. /*    blocks     - total number of pixel blocks             */
  446. /*  Returns     : none                          */
  447. /*  Called by   : DFCimcomp()                       */
  448. /*  Calls       : none                          */
  449. /************************************************************************/
  450.  
  451. static void fillin_color(blocks)
  452. int blocks;
  453. {
  454.   int i, j, k;
  455.  
  456.   for (i=0; i<blocks; i++)
  457.     for (j=HI; j<=LO; j++)
  458.     {
  459.       k = indx(color_pt[2*i+j].c[RED],color_pt[2*i+j].c[GREEN],
  460.            color_pt[2*i+j].c[BLUE]);
  461.       image[i*4+2+j] = trans[k];
  462.     }
  463. } /* end of fillin_color */
  464.  
  465.  
  466.  
  467.  
  468.  
  469. /************************************************************************/
  470. /*  Function    : indx                          */
  471. /*  Purpose : Maps an rgb triple (5 bits each) to an integer array  */
  472. /*        index                         */
  473. /*  Parameter   :                           */
  474. /*    r, g, b    - color components                 */
  475. /*  Returns     : returns an array index                */
  476. /*  Called by   : set_palette(), fillin_color(), map()                  */
  477. /*  Calls       : none                          */
  478. /************************************************************************/
  479.  
  480. static int indx(r, g, b)
  481. unsigned char r, g, b;
  482. {
  483.   int temp;
  484.  
  485.   temp = 0;
  486.   temp = ((r & 0x1f) << 10) | ((g & 0x1f)  << 5) | (b & 0x1f);
  487.   return temp;
  488. } /* end of indx */
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495. /************************************************************************/
  496. /*  Function    : map                           */
  497. /*  Purpose : Maps a color_pt to the closest representative color   */
  498. /*        Sets up translation table             */
  499. /*  Parameter   :                           */
  500. /*    blocks     - total number of pixel blocks             */
  501. /*  Returns     : none                          */
  502. /*  Called by   : DFCimcomp()                       */
  503. /*  Calls       : nearest_color()                   */
  504. /************************************************************************/
  505.  
  506. static void map(blocks)
  507. int blocks;
  508. {
  509.   int i, k;
  510.   unsigned char r, g, b;
  511.   int indx();
  512.   int nearest_color();
  513.  
  514.   for (i=0; i<(2*blocks); i++)
  515.   {
  516.     k = indx(color_pt[i].c[RED], color_pt[i].c[GREEN], color_pt[i].c[BLUE]);
  517.  
  518.     if (trans[k] == -1)
  519.     {
  520.       r = (unsigned char) color_pt[i].c[RED]<<3;
  521.       g = (unsigned char) color_pt[i].c[GREEN]<<3;
  522.       b = (unsigned char) color_pt[i].c[BLUE]<<3;
  523.       trans[k] = nearest_color(r, g, b);
  524. /*
  525.       printf("map: %d %d %d mapped to %d %d %d\n", r, g, b, new_pal[trans[k]*3],
  526.           new_pal[trans[k]*3+1], new_pal[trans[k]*3+2]);
  527. */
  528.     }
  529.   }
  530. } /* end of map */
  531.   
  532.  
  533.  
  534.  
  535. /************************************************************************/
  536. /*  Function    : nearest_color                     */
  537. /*  Purpose : Finds the nearest palette color           */
  538. /*  Parameter   :                           */
  539. /*    r, g, b    - color component                  */
  540. /*  Returns     : Entry number of the closest color in the palette      */
  541. /*  Called by   : map()                         */
  542. /*  Calls       : sqr()                         */
  543. /************************************************************************/
  544.  
  545. static int nearest_color(r, g, b)
  546. unsigned char r, g, b;
  547. {
  548.   int i, near; 
  549.   long int min, error;
  550.   long int sqr();
  551.  
  552.   min = sqr(r-new_pal[0]) + sqr(g-new_pal[1]) + sqr(b-new_pal[2]);
  553.   near = 0;
  554.   for (i=1; i<PALSIZE; i++)
  555.   {
  556.     error = sqr(r-new_pal[3*i]) + sqr(g-new_pal[3*i+1]) + 
  557.         sqr(b-new_pal[3*i+2]);
  558.     if (error < min)
  559.     {
  560.     min = error;
  561.         near = i;
  562.     }
  563.   }
  564.  
  565.   return near;
  566. } /* end of nearest_color */
  567.  
  568.  
  569.  
  570.  
  571. /************************************************************************/
  572. /*  Function    : sqr                           */
  573. /*  Purpose : Computes the square of an integer         */
  574. /*  Parameter   :                           */
  575. /*    x      - an integer                       */
  576. /*  Returns     : The square of x                   */
  577. /*  Called by   : nearest_color()                   */
  578. /*  Calls       : none                          */
  579. /************************************************************************/
  580.  
  581. static long int sqr(x)
  582. unsigned char x;
  583. {
  584.   return (x*x);
  585. }
  586.  
  587.  
  588.  
  589.  
  590.  
  591. /************************************************************************/
  592. /*  Function    : DFCunimcomp                       */
  593. /*  Purpose : 'Decompresses' the compressed image           */
  594. /*  Parameter   :                           */
  595. /*    xdim, ydim - dimensions of image                  */
  596. /*    in, out    - Input buffer and output buffer. Size of input buffer */
  597. /*         is (xdim*ydim)/4. Size of output buffer is 4 times   */
  598. /*         that. It 'restores' images into seq-type files       */
  599. /*  Returns     : none                          */
  600. /*  Called by   : External routines                 */
  601. /*  Calls       : none                          */
  602. /************************************************************************/
  603.  
  604. void DFCunimcomp(xdim, ydim, in, out)
  605. int32 xdim, ydim;
  606. char in[], out[];
  607. {
  608.   int bitmap, temp;
  609.   int i, j, k, x, y;
  610.   unsigned char hi_color, lo_color;
  611.  
  612.   for (y=0; y<(ydim/4); y++)
  613.     for (x=0; x<xdim; x=x+4)
  614.     {
  615.       k = y*xdim + x;
  616.       hi_color = (unsigned char) in[k+2]; 
  617.       lo_color = (unsigned char) in[k+3];
  618.  
  619.       bitmap = ((unsigned char)in[k] << 8) | (unsigned char)in[k+1];
  620.  
  621.       for (i=(y*4); i<(y*4+4); i++)
  622.       {
  623.         temp = bitmap >> (3 + y*4 - i)*4;
  624.         for (j=x; j<(x+4); j++)
  625.         {
  626.       if ((temp & 8) == 8)
  627.         out[i*xdim+j] = (char) hi_color;
  628.       else
  629.         out[i*xdim+j] = (char) lo_color;
  630.       temp = temp << 1;
  631.     }
  632.       }
  633.     } /* end of for x */
  634. } /* end of DFCunimcomp */
  635.  
  636.  
  637.  
  638. /************************************************************************/
  639. /*  Module Name : color                         */
  640. /*  Exports     : sel_palette(); new_pal, pointer to a new color palette*/
  641. /*  Purpose     : Quantizes colors                  */
  642. /*  Author  : Eng-Kiat Koh                      */
  643. /*  Date    : June 30th, 1988                   */
  644. /*  Functions   : sel_palette(), init(), sort(), partition(), find_box()*/
  645. /*        split_box(), assign_color(), select_dim(), find_med() */
  646. /*                classify(), next_pt()                                 */
  647. /************************************************************************/
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655. /************************************************************************/
  656. /*  Function    : sel_palette                       */
  657. /*  Purpose : Selects PALSIZE palette colors out of a list of colors*/
  658. /*        in color_pt                       */
  659. /*  Parameter   :                           */
  660. /*    blocks     - number of pixel blocks               */
  661. /*    distinct   - number of distinct colors                */
  662. /*    color_pt   - contains the lo hi colors for each pixel block       */
  663. /*  Returns     : none                          */
  664. /*  Called by   : DFCimcomp()                       */
  665. /*  Calls       : init(), split_box(), find_box(), assign_color()   */
  666. /************************************************************************/
  667.  
  668. static void sel_palette(blocks,distinct, color_pt)
  669. int blocks, distinct;
  670. struct rgb *color_pt;
  671. {
  672.   int boxes;
  673. /*  int i, j;*/
  674.   struct box *ptr;
  675.   struct box *find_box();
  676.   void init(int, int, struct rgb *);
  677.   void split_box();
  678.   void assign_color();
  679.  
  680.   init(blocks, distinct, color_pt);
  681.  
  682.   /* split box into smaller boxes with about equal number of points */
  683.   for (boxes=1; boxes < PALSIZE; boxes++)
  684.   {
  685. /*
  686.     ptr=frontier->right;
  687.     j = 0;
  688.     while (ptr != NULL)
  689.     {
  690.       printf("Box %d, distinct %d, total %d\n",j,ptr->nmbr_distinct,
  691.              ptr->nmbr_pts);
  692.       for (i=0; i<ptr->nmbr_distinct; i++)
  693.         printf("pt %d: %d %d %d",i,distinct_pt[ptr->pts[i]].c[RED],
  694.                 distinct_pt[ptr->pts[i]].c[GREEN], 
  695.             distinct_pt[ptr->pts[i]].c[BLUE]);
  696.       j++;
  697.       ptr = ptr->right;
  698.     }
  699. */
  700.  
  701.     ptr = find_box();
  702.     split_box(ptr);
  703.   } 
  704.  
  705.   assign_color();
  706. }
  707.  
  708.  
  709.  
  710.  
  711.  
  712.  
  713. /************************************************************************/
  714. /*  Function    : init                          */
  715. /*  Purpose : Initializes the global variables, sets up the first   */
  716. /*        box. It will contain all the color points     */
  717. /*  Parameter   :                           */
  718. /*    blocks     - number of pixel blocks               */
  719. /*    distinct   - number of distinct colors                */
  720. /*    color_pt   - contains the lo hi colors for each pixel block       */
  721. /*  Returns     : none                          */
  722. /*  Called by   : sel_palette()                     */
  723. /*  Calls       : none                          */
  724. /************************************************************************/
  725.  
  726. static void init(blocks, distinct, color_pt)
  727. int blocks, distinct;
  728. struct rgb *color_pt;
  729. {
  730.   int i, j, k, l;
  731.   int temp[MAXCOLOR];
  732.   struct box *first;
  733.   struct box *dummy;
  734.  
  735.   /* alloc memory */
  736.   if (hist) DFIfreespace((char *) hist);
  737.   if (distinct_pt) DFIfreespace((char*) distinct_pt);
  738.   hist = (int *)DFIgetspace((unsigned)distinct * sizeof(int));
  739.   distinct_pt = (struct rgb *)DFIgetspace((unsigned)distinct *
  740.                       sizeof(struct rgb));
  741.  
  742.   for (i=0; i<distinct; i++)
  743.     hist[i] = 0;
  744.  
  745.  
  746.   /* select distinct pts and set up histogram */
  747.   for (i=0; i<MAXCOLOR; i++)
  748.     temp[i] = -1;
  749.  
  750.   k = 0;
  751.   for (i=0; i<(2*blocks); i++)
  752.   {
  753.     j = (color_pt[i].c[RED] << 10) | (color_pt[i].c[GREEN] << 5) |
  754.         color_pt[i].c[BLUE];
  755.  
  756.     if (temp[j] == -1)
  757.     {
  758.       /* new pt */
  759.       temp[j] = k;
  760.       for (l=RED; l<=BLUE; l++)
  761.     distinct_pt[k].c[l] = color_pt[i].c[l];
  762.       k++;
  763.    }
  764.  
  765.    hist[temp[j]]++;
  766.   }
  767.  
  768.       
  769.   /* set up first box */
  770.   first = (struct box *)DFIgetspace(sizeof(struct box));
  771.   for (i=RED; i<=BLUE; i++)
  772.   {
  773.     first->bnd[i][LO] = 999.9;
  774.     first->bnd[i][HI] = -999.9;
  775.  
  776.     for (j=0; j<distinct; j++)
  777.     {
  778.       if (first->bnd[i][LO] > (float)distinct_pt[j].c[i])
  779.     first->bnd[i][LO] = (float)distinct_pt[j].c[i];
  780.  
  781.       if (first->bnd[i][HI] < (float)distinct_pt[j].c[i])
  782.     first->bnd[i][HI] = (float)distinct_pt[j].c[i];
  783.     } /* end of for j */
  784.  
  785.     first->bnd[i][LO] = first->bnd[i][LO] - EPSILON;
  786.     first->bnd[i][HI] = first->bnd[i][HI] + EPSILON;
  787.   } /* end of for i */
  788.  
  789.   first->pts = (int *)DFIgetspace((unsigned)distinct * sizeof(int));
  790.   for (i=0; i<distinct; i++)
  791.     first->pts[i] = i;
  792.   first->nmbr_pts = 2*blocks;
  793.   first->nmbr_distinct = distinct;
  794.  
  795.   dummy = (struct box *)DFIgetspace(sizeof(struct box));
  796.   frontier = dummy;
  797.   dummy->right = first;
  798.   first->left = dummy;
  799.   first->right = NULL;
  800.   dummy->nmbr_pts = 0;
  801.  
  802.   DFIfreespace((char *)first);
  803.   DFIfreespace((char *)dummy);
  804. } /* end of init */
  805.  
  806.  
  807.  
  808.  
  809.  
  810.  
  811.  
  812. /************************************************************************/
  813. /*  Function    : sort                          */
  814. /*  Purpose : Performs quick sort on the points in a box along a    */
  815. /*        given dimension                   */
  816. /*  Parameter   :                           */
  817. /*    l, r   - index of leftmost and rightmost element      */
  818. /*    dim    - dimension along which sorting is done        */
  819. /*    rank   - an array which carries the index of the points to be */
  820. /*         sorted                       */
  821. /*  Returns     : none                          */
  822. /*  Called by   : find_med()                        */
  823. /*  Calls       : partition()                       */
  824. /************************************************************************/
  825.  
  826. static void sort(l,r,dim, rank)
  827. int l, r, dim, rank[];
  828. {
  829.   int i;
  830.   int partition();
  831.   void sort();
  832.  
  833.   if (r > l)
  834.   {
  835.     i = partition(l, r, dim, rank);
  836.     sort(l, i-1, dim, rank);
  837.     sort(i+1, r, dim, rank);
  838.   }
  839. }
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846. /************************************************************************/
  847. /*  Function    : partition                     */
  848. /*  Purpose : Partitions the list into 2 parts as in the quick sort */
  849. /*        algorithm                     */
  850. /*  Parameter   :                           */
  851. /*    l, r   - index of leftmost and rightmost element      */
  852. /*    dim    - dimension along which sorting is done        */
  853. /*    rank   - an array which carries the index of the points to be */
  854. /*  Returns     : index where list is partitioned           */
  855. /*  Called by   : sort()                        */
  856. /*  Calls       : none                          */
  857. /************************************************************************/
  858.  
  859. static int partition(l, r, dim, rank)
  860. int l, r, dim, rank[];
  861. {
  862.   int i, j, temp;
  863.   char v;
  864.   
  865.   v = distinct_pt[rank[r]].c[dim];
  866.   i = l-1;
  867.   j = r;
  868.  
  869.   /* repeat until i and j crosses */
  870.   do
  871.   {
  872.     /* repeat until an element >= v is found */
  873.     do
  874.       i++;
  875.     while (distinct_pt[rank[i]].c[dim] < v);
  876.  
  877.     /* repeat until an element <= v is found */
  878.     do
  879.       j--;
  880.     while ((j>0) && (distinct_pt[rank[j]].c[dim] > v));
  881.  
  882.     /* swap pointers */
  883.     temp = rank[i];
  884.     rank[i] = rank[j];
  885.     rank[j] = temp;
  886.   }
  887.   while (i < j);
  888.  
  889.   /* position partitioning element at location i */
  890.   temp = rank[j];
  891.   rank[j] = rank[i];
  892.   rank[i] = rank[r];
  893.   rank[r] = temp;
  894.  
  895.   return i;
  896. }
  897.  
  898.  
  899.  
  900.  
  901.  
  902. /************************************************************************/
  903. /*  Function    : find_box                      */
  904. /*  Purpose : Finds the box with the largest number of color points */
  905. /*        The points need not necessarily be distinct. But in   */
  906. /*        order to partition the box, there must be at least  2 */
  907. /*        distinct points                   */
  908. /*  Parameter   : none                          */
  909. /*  Returns     : pointer to box selected for splitting         */
  910. /*  Called by   : sel_palette()                     */
  911. /*  Calls       : none                          */
  912. /************************************************************************/
  913.  
  914. static struct box *find_box()
  915. {
  916.   struct box *temp;
  917.   struct box *max;
  918.   int max_pts;
  919.  
  920.   max_pts = 1;
  921.   max = NULL;
  922.   temp = frontier->right;
  923.   while (temp != NULL)
  924.     if ((temp->nmbr_distinct > 1) && (max_pts < temp->nmbr_pts))
  925.     {
  926.       max_pts = temp->nmbr_pts;
  927.       max = temp;
  928.       temp = temp->right;
  929.     }
  930.     else
  931.       temp = temp->right;
  932.  
  933.   if (max == NULL)
  934.   {
  935.     printf("Error : Number of color points < palette \n");
  936.     exit(1);
  937.   }
  938.  
  939.   return max;
  940. }
  941.  
  942.  
  943.  
  944.  
  945.  
  946. /************************************************************************/
  947. /*  Function    : split_box                     */
  948. /*  Purpose : Splits a selected box into 2 and reinserts the 2 sub- */
  949. /*        boxes into the frontier list              */
  950. /*  Parameter   :                           */
  951. /*    ptr    - pointer to box to be split               */
  952. /*  Returns     : none                          */
  953. /*  Called by   : sel_palette()                     */
  954. /*  Calls       : find_med(), select_dim(), classify()          */
  955. /************************************************************************/
  956.  
  957. static void split_box(ptr)
  958. struct box *ptr;
  959. {
  960.   int dim, j, i;
  961.   float median;
  962.   struct box *l_child, *r_child;
  963.   int select_dim();
  964.   float find_med();
  965.   void classify();
  966.   
  967.   dim = select_dim(ptr);
  968.   median = find_med(ptr, dim);
  969.  
  970.   /* create 2 child */
  971.   l_child = (struct box *)DFIgetspace(sizeof(struct box));
  972.   r_child = (struct box *)DFIgetspace(sizeof(struct box));
  973.   
  974.   for (i=RED; i<=BLUE; i++)
  975.     for (j=HI; j<=LO; j++)
  976.     {
  977.       l_child->bnd[i][j] = ptr->bnd[i][j];
  978.       r_child->bnd[i][j] = ptr->bnd[i][j];
  979.     }
  980.   l_child->bnd[dim][HI] = median;
  981.   r_child->bnd[dim][LO] = median;
  982.  
  983.   classify(ptr,l_child);
  984.   classify(ptr,r_child);
  985.  
  986.   r_child->right = ptr->right;
  987.   r_child->left = l_child;
  988.   l_child->right = r_child;
  989.   l_child->left = ptr->left;
  990.   (ptr->left)->right = l_child;
  991.   if (ptr->right != NULL)
  992.     (ptr->right)->left = r_child;
  993. } /* end of split_box */
  994.  
  995.  
  996.  
  997.  
  998.  
  999.  
  1000. /************************************************************************/
  1001. /*  Function    : assign_color                      */
  1002. /*  Purpose : Assigns a color to each box. It computes the average  */
  1003. /*        color of all the points in the box            */
  1004. /*        Sets up the new_pal buffer. Each color component is   */
  1005. /*        shifted left 3 bits because of the truncation when    */
  1006. /*        color_pt was set up                   */
  1007. /*  Parameter   : none                          */
  1008. /*  Returns     : none                          */
  1009. /*  Called by   : sel_palette()                     */
  1010. /*  Calls       : none                          */
  1011. /************************************************************************/
  1012.  
  1013.  
  1014. static void assign_color()
  1015. {
  1016.   struct box *temp;
  1017.   int ent, k, j;
  1018.   int c[3];
  1019.  
  1020.   temp = frontier->right;
  1021.   for (ent=0; ent<PALSIZE; ent++)
  1022.   {
  1023.     for (k=RED; k<=BLUE; k++)
  1024.       c[k] = 0;
  1025.  
  1026. /*
  1027.     printf("Box %d: number of pts %d\n", ent, temp->nmbr_pts);
  1028. */
  1029.  
  1030.     for (j=0; j<temp->nmbr_distinct; j++)
  1031.     {
  1032. /*
  1033.       printf("pt %d:", j);
  1034. */
  1035.       for (k=RED; k<=BLUE; k++)
  1036.       {
  1037. /*
  1038.         printf("%d ",distinct_pt[temp->pts[j]].c[k]);
  1039. */
  1040.     c[k] = c[k] + distinct_pt[temp->pts[j]].c[k]*hist[temp->pts[j]];
  1041.       }
  1042. /*
  1043.       printf("\n");
  1044. */
  1045.     }
  1046.  
  1047.     for (k=RED; k<=BLUE; k++)
  1048.     {
  1049.       c[k] = c[k] / temp->nmbr_pts;
  1050.       new_pal[3*ent+k] = c[k] << 3;
  1051.     }
  1052.     
  1053.     temp = temp->right;
  1054.   } /* end of for entry */
  1055. }
  1056.  
  1057.  
  1058.  
  1059.  
  1060.  
  1061. /************************************************************************/
  1062. /*  Function    : select_dim                        */
  1063. /*  Purpose : Selects the dimension with the largest spread         */
  1064. /*  Parameter   :                           */
  1065. /*    ptr    - pointer to desired box               */
  1066. /*  Returns     : dimension where the box is to be split        */
  1067. /*  Called by   : split_box()                       */
  1068. /*  Calls       : none                          */
  1069. /************************************************************************/
  1070.  
  1071. static int select_dim(ptr)
  1072. struct box *ptr;
  1073. {
  1074.   int i, j, low[3], high[3];
  1075.   int max;
  1076.  
  1077.  
  1078.   for (j=RED; j<=BLUE; j++)
  1079.   {
  1080.     low[j] = distinct_pt[ptr->pts[0]].c[j];
  1081.     high[j] = distinct_pt[ptr->pts[0]].c[j];
  1082.   }
  1083.  
  1084.   for (i=1; i<ptr->nmbr_distinct; i++)
  1085.     for (j=RED; j<=BLUE; j++)
  1086.     {
  1087.       if (low[j] > distinct_pt[ptr->pts[i]].c[j])
  1088.     low[j] = distinct_pt[ptr->pts[i]].c[j];
  1089.       if (high[j] < distinct_pt[ptr->pts[i]].c[j])
  1090.     high[j] = distinct_pt[ptr->pts[i]].c[j];
  1091.     }
  1092.  
  1093.   max = high[RED] - low[RED];
  1094.   i = RED;
  1095.   for (j=GREEN; j<=BLUE; j++)
  1096.     if (max < (high[j] - low[j]))
  1097.     {
  1098.       max = high[j] - low[j];
  1099.       i = j;
  1100.     }
  1101.  
  1102.   return i;
  1103. } /* end of select_dim */
  1104.  
  1105.  
  1106.  
  1107.  
  1108.  
  1109. /************************************************************************/
  1110. /*  Function    : find_med                      */
  1111. /*  Purpose : Finds the point where the box is to be split. It finds*/
  1112. /*        a point such that the 2 new boxes have about the same */
  1113. /*        number of color points.               */
  1114. /*  Parameter   :                           */
  1115. /*    ptr    - pointer to box to be split               */
  1116. /*    dim    - dimension to split box               */
  1117. /*  Returns     : point where the box is to be cut          */
  1118. /*  Called by   : split_box()                       */
  1119. /*  Calls       : next_pt()                     */
  1120. /************************************************************************/
  1121.  
  1122. static float find_med(ptr,dim)
  1123. struct box *ptr;
  1124. int dim;
  1125. {
  1126.   int i, j, count, next, prev;
  1127.   int *rank;
  1128.   float median;
  1129.   int next_pt();
  1130.   void sort();
  1131.  
  1132.   rank = (int *)DFIgetspace((unsigned)ptr->nmbr_distinct * sizeof(int));
  1133.   for (i=0; i<ptr->nmbr_distinct; i++)
  1134.     rank[i] = ptr->pts[i];
  1135.  
  1136.   sort(0,ptr->nmbr_distinct-1,dim,rank);
  1137. /*
  1138.   for (i=0; i<ptr->nmbr_distinct; i++)
  1139.     printf("find_med: sorted list is %d\n",distinct_pt[rank[i]].c[dim]);
  1140. */
  1141.   
  1142.  
  1143.   count = 0;
  1144.   i = 0;
  1145.   while ((i < ptr->nmbr_distinct) && (count < ptr->nmbr_pts/2))
  1146.   {
  1147.     next = next_pt(dim, i, rank, ptr->nmbr_distinct);
  1148.     for (j=i; j<next; j++)
  1149.       count = count + hist[rank[j]];
  1150.  
  1151.     prev = i;
  1152.     i = next; 
  1153.   }
  1154.  
  1155.   if (prev == 0)
  1156.   {
  1157.     /* the first distinct point overshot the median */
  1158.     median = (float)distinct_pt[rank[prev]].c[dim] + EPSILON;
  1159.   }
  1160.   else
  1161.     median = (float)distinct_pt[rank[prev-1]].c[dim] + EPSILON;
  1162.    
  1163.   DFIfreespace((char *) rank);
  1164.   return median;
  1165. } /* end of find_med */
  1166.   
  1167.  
  1168.  
  1169.  
  1170.  
  1171.  
  1172. /************************************************************************/
  1173. /*  Function    : classify                      */
  1174. /*  Purpose : Looks at the color points in the parent and selects   */
  1175. /*        the points that belong to the child           */
  1176. /*  Parameter   :                           */
  1177. /*    ptr    - pointer to parent                    */
  1178. /*    child  - pointer to child box                 */
  1179. /*  Returns     : none                          */
  1180. /*  Called by   : split_box()                       */
  1181. /*  Calls       : none                          */
  1182. /************************************************************************/
  1183.  
  1184. static void classify(ptr, child)
  1185. struct box *ptr, *child;
  1186. {
  1187.   int i, j;
  1188.   int *temp;
  1189.   int distinct, total;
  1190.  
  1191.   temp = (int *)DFIgetspace((unsigned)ptr->nmbr_distinct * sizeof(int));
  1192.  
  1193.   distinct = 0;
  1194.   total = 0;
  1195.   for (i=0; i<ptr->nmbr_distinct; i++)
  1196.   {
  1197.     j = ptr->pts[i];
  1198.     if ((((float)distinct_pt[j].c[RED] >= child->bnd[RED][LO]) &&
  1199.          ((float)distinct_pt[j].c[RED] <= child->bnd[RED][HI])) &&
  1200.         (((float)distinct_pt[j].c[GREEN] >= child->bnd[GREEN][LO]) &&
  1201.          ((float)distinct_pt[j].c[GREEN] <= child->bnd[GREEN][HI])) &&
  1202.         (((float)distinct_pt[j].c[BLUE] >= child->bnd[BLUE][LO]) &&
  1203.          ((float)distinct_pt[j].c[BLUE] <= child->bnd[BLUE][HI])))
  1204.     {
  1205.       /* pt is in new box */
  1206.       temp[distinct] = j;
  1207.       distinct++;
  1208.       total = total + hist[j];
  1209.     } /* end of if */
  1210.   } /* end of for i */
  1211.  
  1212.   /* assign points */
  1213.   child->nmbr_pts = total;
  1214.   child->nmbr_distinct = distinct;
  1215.   child->pts = (int *)DFIgetspace((unsigned)distinct * sizeof(int));
  1216.   for (i=0; i<distinct; i++)
  1217.     child->pts[i] = temp[i];
  1218.  
  1219.   DFIfreespace((char *)temp);
  1220.  
  1221. } /* end of classify */
  1222.  
  1223.  
  1224.  
  1225.  
  1226.  
  1227. /************************************************************************/
  1228. /*  Function    : next_pt                       */
  1229. /*  Purpose : Determines the next point that has a different value  */
  1230. /*        from the current point along  a dimension     */
  1231. /*  Parameter   :                           */
  1232. /*    dim    - dimension where box is to be split           */
  1233. /*    i      - index to current point               */
  1234. /*    rank       - sorted list of points to be searched starting from i */
  1235. /*    distinct   - length of sorted list                                */
  1236. /*  Returns     : index of point that has a different value     */
  1237. /*  Called by   : find_med                      */
  1238. /*  Calls       : none                          */
  1239. /************************************************************************/
  1240.  
  1241. static int next_pt(dim, i, rank, distinct)
  1242. int dim, i, rank[], distinct;
  1243. {
  1244.   int j;
  1245.   char old;
  1246.  
  1247.   old = distinct_pt[rank[i]].c[dim];
  1248.   for (j=(i+1); j<distinct; j++)
  1249.     if (distinct_pt[rank[j]].c[dim] != old)
  1250.       break;
  1251.  
  1252.   return j;
  1253. } /* end of next_pt */
  1254.  
  1255.